using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SilkSharp
{
	/**
	 *This class contains a number of defines that controls the operation of SILK.
	 *Most of these should be left alone for ensuring proper operation. 
	 *However, a few can be changed if operation different from the default is desired.
	 *
	 * @author Jing Dai
	 * @author Dingxin Xu
	 */
	public class Silk_define
	{
		public const int MAX_FRAMES_PER_PACKET = 5;

		/* MAX DELTA LAG used for multiframe packets */
		public const int MAX_DELTA_LAG = 10;

		/* Lower limit on bitrate for each mode */
		public const int MIN_TARGET_RATE_NB_BPS = 5000;
		public const int MIN_TARGET_RATE_MB_BPS = 7000;
		public const int MIN_TARGET_RATE_WB_BPS = 8000;
		public const int MIN_TARGET_RATE_SWB_BPS = 20000;

		/* Transition bitrates between modes */
		public const int SWB2WB_BITRATE_BPS = 26000;
		public const int WB2SWB_BITRATE_BPS = 32000;
		public const int WB2MB_BITRATE_BPS = 15000;
		public const int MB2WB_BITRATE_BPS = 20000;
		public const int MB2NB_BITRATE_BPS = 10000;
		public const int NB2MB_BITRATE_BPS = 14000;

		/* Integration/hysteresis threshold for lowering internal sample frequency */
		/* 30000000 -> 6 sec if bitrate is 5000 bps below limit; 3 sec if bitrate is 10000 bps below limit */
		public const int ACCUM_BITS_DIFF_THRESHOLD = 30000000;
		public const int TARGET_RATE_TAB_SZ = 8;

		/* DTX settings                                 */
		public const int NO_SPEECH_FRAMES_BEFORE_DTX = 5;       /* eq 100 ms */
		public const int MAX_CONSECUTIVE_DTX = 20;      /* eq 400 ms */

		public const int USE_LBRR = 1;

		/* Amount of concecutive no FEC packets before telling JB */
		public const int NO_LBRR_THRES = 10;

		/* Maximum delay between real packet and LBRR packet */
		public const int MAX_LBRR_DELAY = 2;
		public const int LBRR_IDX_MASK = 1;

		public const int INBAND_FEC_MIN_RATE_BPS = 18000;  /* Dont use inband FEC below this total target rate  */
		public const int LBRR_LOSS_THRES = 2;   /* Start adding LBRR at this loss rate (needs tuning)   */

		/* LBRR usage defines */
		public const int SKP_SILK_NO_LBRR = 0;   /* No LBRR information for this packet                  */
		public const int SKP_SILK_ADD_LBRR_TO_PLUS1 = 1;   /* Add LBRR for this packet to packet n + 1             */
		public const int SKP_SILK_ADD_LBRR_TO_PLUS2 = 2;   /* Add LBRR for this packet to packet n + 2             */

		/* Frame termination indicator defines */
		public const int SKP_SILK_LAST_FRAME = 0;   /* Last frames in packet                                */
		public const int SKP_SILK_MORE_FRAMES = 1;   /* More frames to follow this one                       */
		public const int SKP_SILK_LBRR_VER1 = 2;  /* LBRR information from packet n - 1                   */
		public const int SKP_SILK_LBRR_VER2 = 3;   /* LBRR information from packet n - 2                   */
		public const int SKP_SILK_EXT_LAYER = 4;   /* Extension layers added                               */

		/* Number of Second order Sections for SWB detection HP filter */
		public const int NB_SOS = 3;
		public const int HP_8_KHZ_THRES = 10;          /* average energy per sample, above 8 kHz       */
		public const int CONCEC_SWB_SMPLS_THRES = 480 * 15;    /* 300 ms                                       */
		public const int WB_DETECT_ACTIVE_SPEECH_MS_THRES = 15000;       /* ms of active speech needed for WB detection  */

		/* Low complexity setting */
		public const int LOW_COMPLEXITY_ONLY = 0;

		/* Activate bandwidth transition filtering for mode switching */
		public const int SWITCH_TRANSITION_FILTERING = 1;

		/* Decoder Parameters */
		public const int DEC_HP_ORDER = 2;

		/* Maximum sampling frequency, should be 16 for embedded */
		public const int MAX_FS_KHZ = 24;
		public const int MAX_API_FS_KHZ = 48;

		/* Signal Types used by silk */
		public const int SIG_TYPE_VOICED = 0;
		public const int SIG_TYPE_UNVOICED = 1;

		/* VAD Types used by silk */
		public const int NO_VOICE_ACTIVITY = 0;
		public const int VOICE_ACTIVITY = 1;

		/* Number of samples per frame */
		public const int FRAME_LENGTH_MS = 20; /* 20 ms */
		public const int MAX_FRAME_LENGTH = ( FRAME_LENGTH_MS * MAX_FS_KHZ );

		/* Milliseconds of lookahead for pitch analysis */
		public const int LA_PITCH_MS = 3;
		public const int LA_PITCH_MAX = ( LA_PITCH_MS * MAX_FS_KHZ );

		/* Milliseconds of lookahead for noise shape analysis */
		public const int LA_SHAPE_MS = 5;
		public const int LA_SHAPE_MAX = ( LA_SHAPE_MS * MAX_FS_KHZ );

		/* Order of LPC used in find pitch */
		public const int FIND_PITCH_LPC_ORDER_MAX = 16;

		/* Length of LPC window used in find pitch */
		public const int FIND_PITCH_LPC_WIN_MS = ( 30 + ( LA_PITCH_MS << 1 ) );
		public const int FIND_PITCH_LPC_WIN_MAX = ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ );

		public const int PITCH_EST_COMPLEXITY_HC_MODE = Silk_SigProc_FIX.SKP_Silk_PITCH_EST_MAX_COMPLEX;
		public const int PITCH_EST_COMPLEXITY_MC_MODE = Silk_SigProc_FIX.SKP_Silk_PITCH_EST_MID_COMPLEX;
		public const int PITCH_EST_COMPLEXITY_LC_MODE = Silk_SigProc_FIX.SKP_Silk_PITCH_EST_MIN_COMPLEX;


		/* Max number of bytes in payload output buffer (may contain multiple frames) */
		public const int MAX_ARITHM_BYTES = 1024;

		public const int RANGE_CODER_WRITE_BEYOND_BUFFER = -1;
		public const int RANGE_CODER_CDF_OUT_OF_RANGE = -2;
		public const int RANGE_CODER_NORMALIZATION_FAILED = -3;
		public const int RANGE_CODER_ZERO_INTERVAL_WIDTH = -4;
		public const int RANGE_CODER_DECODER_CHECK_FAILED = -5;
		public const int RANGE_CODER_READ_BEYOND_BUFFER = -6;
		public const int RANGE_CODER_ILLEGAL_SAMPLING_RATE = -7;
		public const int RANGE_CODER_DEC_PAYLOAD_TOO_LONG = -8;

		/* dB level of lowest gain quantization level */
		public const int MIN_QGAIN_DB = 6;
		/* dB level of highest gain quantization level */
		public const int MAX_QGAIN_DB = 86;
		/* Number of gain quantization levels */
		public const int N_LEVELS_QGAIN = 64;
		/* Max increase in gain quantization index */
		public const int MAX_DELTA_GAIN_QUANT = 40;
		/* Max decrease in gain quantization index */
		public const int MIN_DELTA_GAIN_QUANT = -4;

		/* Quantization offsets (multiples of 4) */
		public const int OFFSET_VL_Q10 = 32;
		public const int OFFSET_VH_Q10 = 100;
		public const int OFFSET_UVL_Q10 = 100;
		public const int OFFSET_UVH_Q10 = 256;

		/* Maximum numbers of iterations used to stabilize a LPC vector */
		public const int MAX_LPC_STABILIZE_ITERATIONS = 20;

		public const int MAX_LPC_ORDER = 16;
		public const int MIN_LPC_ORDER = 10;

		/* Find Pred Coef defines */
		public const int LTP_ORDER = 5;

		/* LTP quantization settings */
		public const int NB_LTP_CBKS = 3;

		/* Number of subframes */
		public const int NB_SUBFR = 4;

		/* Flag to use harmonic noise shaping */
		public const int USE_HARM_SHAPING = 1;

		/* Max LPC order of noise shaping filters */
		public const int SHAPE_LPC_ORDER_MAX = 16;

		public const int HARM_SHAPE_FIR_TAPS = 3;

		/* Length of LPC window used in noise shape analysis */
		public const int SHAPE_LPC_WIN_MS = 15;
		public const int SHAPE_LPC_WIN_16_KHZ = ( SHAPE_LPC_WIN_MS * 16 );
		public const int SHAPE_LPC_WIN_24_KHZ = ( SHAPE_LPC_WIN_MS * 24 );
		public const int SHAPE_LPC_WIN_MAX = ( SHAPE_LPC_WIN_MS * MAX_FS_KHZ );

		/* Maximum number of delayed decision states */
		public const int DEL_DEC_STATES_MAX = 4;

		public const int LTP_BUF_LENGTH = 512;
		public const int LTP_MASK = ( LTP_BUF_LENGTH - 1 );

		public const int DECISION_DELAY = 32;
		public const int DECISION_DELAY_MASK = ( DECISION_DELAY - 1 );

		/* number of subframes for excitation entropy coding */
		public const int SHELL_CODEC_FRAME_LENGTH = 16;
		public const int MAX_NB_SHELL_BLOCKS = ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH );

		/* number of rate levels, for entropy coding of excitation */
		public const int N_RATE_LEVELS = 10;

		/* maximum sum of pulses per shell coding frame */
		public const int MAX_PULSES = 18;

		public const int MAX_MATRIX_SIZE = MAX_LPC_ORDER; /* Max of LPC Order and LTP order */

		//TODO: convert a macro to a method.	
		public static int NSQ_LPC_BUF_LENGTH
		{
			get
			{
				if( MAX_LPC_ORDER > DECISION_DELAY )
					return MAX_LPC_ORDER;
				else
					return DECISION_DELAY;
			}
		}
		/***********************/
		/* High pass filtering */
		/***********************/
		public const int HIGH_PASS_INPUT = 1;

		/***************************/
		/* Voice activity detector */
		/***************************/
		public const int VAD_N_BANDS = 4;       /* 0-1, 1-2, 2-4, and 4-8 kHz                       */

		public const int VAD_INTERNAL_SUBFRAMES_LOG2 = 2;
		public const int VAD_INTERNAL_SUBFRAMES = ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 );

		public const int VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 = 1024;    /* Must be <  4096                                  */
		public const int VAD_NOISE_LEVELS_BIAS = 50;

		/* Sigmoid settings */
		public const int VAD_NEGATIVE_OFFSET_Q5 = 128;    /* sigmoid is 0 at -128                             */
		public const int VAD_SNR_FACTOR_Q16 = 45000;

		/* smoothing for SNR measurement */
		public const int VAD_SNR_SMOOTH_COEF_Q18 = 4096;

		/******************/
		/* NLSF quantizer */
		/******************/
		public const int NLSF_MSVQ_MAX_CB_STAGES = 10;  /* Update manually when changing codebooks      */
		public const int NLSF_MSVQ_MAX_VECTORS_IN_STAGE = 128;/* Update manually when changing codebooks      */
		public const int NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END = 16;  /* Update manually when changing codebooks      */

		public const int NLSF_MSVQ_FLUCTUATION_REDUCTION = 1;
		public const int MAX_NLSF_MSVQ_SURVIVORS = 16;
		public const int MAX_NLSF_MSVQ_SURVIVORS_LC_MODE = 2;
		public const int MAX_NLSF_MSVQ_SURVIVORS_MC_MODE = 4;

		/* Based on above defines, calculate how much memory is necessary to allocate */
		public static int NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE
		{
			get
			{
				if( NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ) )
					return NLSF_MSVQ_MAX_VECTORS_IN_STAGE;
				else
					return MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END;
			}
		}

		public static int NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED
		{
			get
			{
				if( NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ) )
					return NLSF_MSVQ_MAX_VECTORS_IN_STAGE;
				else
					return MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END;
			}
		}

		public const int NLSF_MSVQ_SURV_MAX_REL_RD = 4;

		/* Transition filtering for mode switching */
		public const int TRANSITION_TIME_UP_MS = 5120; // 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)
		public const int TRANSITION_TIME_DOWN_MS = 2560; // 2560 = 32 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 32*(20*4)
		public const int TRANSITION_NB = 3; /* Hardcoded in tables */
		public const int TRANSITION_NA = 2; /* Hardcoded in tables */
		public const int TRANSITION_INT_NUM = 5; /* Hardcoded in tables */
		public const int TRANSITION_FRAMES_UP = ( TRANSITION_TIME_UP_MS / FRAME_LENGTH_MS );
		public const int TRANSITION_FRAMES_DOWN = ( TRANSITION_TIME_DOWN_MS / FRAME_LENGTH_MS );
		public const int TRANSITION_INT_STEPS_UP = ( TRANSITION_FRAMES_UP / ( TRANSITION_INT_NUM - 1 ) );
		public const int TRANSITION_INT_STEPS_DOWN = ( TRANSITION_FRAMES_DOWN / ( TRANSITION_INT_NUM - 1 ) );

		//TODO:no need to convert from C to Java?	
		/* Row based */
		//	#define matrix_ptr(Matrix_base_adr, row, column, N)         *(Matrix_base_adr + ((row)*(N)+(column)))
		//	#define matrix_adr(Matrix_base_adr, row, column, N)          (Matrix_base_adr + ((row)*(N)+(column)))

		/* Column based */
		//	#ifndef matrix_c_ptr
		//	#   define matrix_c_ptr(Matrix_base_adr, row, column, M)    *(Matrix_base_adr + ((row)+(M)*(column)))
		//	#endif
		//	#define matrix_c_adr(Matrix_base_adr, row, column, M)        (Matrix_base_adr + ((row)+(M)*(column)))

		/* BWE factors to apply after packet loss */
		public const int BWE_AFTER_LOSS_Q16 = 63570;

		/* Defines for CN generation */
		public const int CNG_BUF_MASK_MAX = 255;             /* 2^floor(log2(MAX_FRAME_LENGTH))  */
		public const int CNG_GAIN_SMTH_Q16 = 4634;            /* 0.25^(1/4)                       */
		public const int CNG_NLSF_SMTH_Q16 = 16348;           /* 0.25                             */
	}
}
